
import java.util.*;

public class MyDemo {
    private static Map<String, String[]> resultMap = new HashMap<>();
    private static List<String> newRaw;

    public static void main(String[] args) {
        String[] rawArr = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
        List<String> rawList = Arrays.asList(rawArr);
        if (rawList.size() > 2) {
            long s = System.nanoTime();
            doSth(rawList);
            System.out.println((System.nanoTime() - s) / Math.pow(10, 6) + " ms");
            System.out.println("size: " + resultMap.size());
        }
        if (rawList.size() > 2) {
            Set<Set<String>> result;
            long s = System.nanoTime();
            result = powerSet(new HashSet<>(rawList));
            System.out.println((System.nanoTime() - s) / Math.pow(10, 6) + " ms");
            System.out.println("size: " + resultMap.size());
        }
        // for (String[] item : resultMap.values()) {
        //     System.out.println(Arrays.toString(item));
        // }
    }

    private static void doSth(List<String> raw) {
        for (int i = 0, s = raw.size(); i < s; i++) {
            newRaw = new ArrayList<>(raw);
            newRaw.remove(i);
            String arr = newRaw.toString();
            resultMap.put(arr, newRaw.toArray(new String[0]));
            if (newRaw.size() > 2) {
                doSth(newRaw);
            }
        }
    }

    // https://stackoverflow.com/a/1670871/5631625
    public static Set<Set<String>> powerSet(Set<String> originalSet) {
        Set<Set<String>> sets = new HashSet<>();
        if (originalSet.isEmpty()) {
            sets.add(new HashSet<>());
            return sets;
        }
        List<String> list = new ArrayList<>(originalSet);
        String head = list.get(0);
        Set<String> rest = new HashSet<>(list.subList(1, list.size()));
        for (Set<String> set : powerSet(rest)) {
            Set<String> newSet = new HashSet<>();
            newSet.add(head);
            newSet.addAll(set);
            sets.add(newSet);
            sets.add(set);
        }
        return sets;
    }
}
